#pragma once

#include "BitSet.h"

namespace BloomFilter {
struct _BKDR__Hash {
  size_t operator()(const std::string& key) {
    size_t hash = 0;
    for (auto e : key) {
      hash *= 31;
      hash += e;
    }
    return hash;
  }
};
struct _AP__Hash {
  size_t operator()(const std::string& key) {
    size_t hash = 0;
    for (size_t i = 0; i < key.size(); i++) {
      char ch = key[i];
      if ((i & 1) == 0) {
        hash ^= ((hash << 7) ^ ch ^ (hash >> 3));
      } else {
        hash ^= (~((hash << 11) ^ ch ^ (hash >> 5)));
      }
    }
    return hash;
  }
};
struct _DJB__Hash {
  size_t operator()(const std::string& key) {
    size_t hash = 5381;
    for (auto ch : key) {
      hash += (hash << 5) + ch;
    }
    return hash;
  }
};

template <size_t N, class K = std::string, class Hash1 = _BKDR__Hash , class Hash2 = _AP__Hash,
          class Hash3 = _DJB__Hash>
class BloomFilter {
 public:
 void set(const K& key){
   size_t len = N * _X;
   size_t hash1 = Hash1()(key) % len;
   _bits.set(hash1);
   size_t hash2 = Hash2()(key) % len;
   _bits.set(hash2);
   size_t hash3 = Hash3()(key) % len;
   _bits.set(hash3);
 }

bool test(const K& key){
  size_t len = N * _X;
  size_t hash1 = Hash1()(key) % len;
  if(!_bits.test(hash1)){
    return false;
  }
  size_t hash2 = Hash2()(key) % len;
  if (!_bits.test(hash2)) {
    return false;
  }
  size_t hash3 = Hash3()(key) % len;
  if (!_bits.test(hash3)) {
    return false;
  }
  else{
    return true;
  }
}
 private:
  const static size_t _X = 5;
  MyBitset::bitset<N*_X> _bits;  // N为数据量最多
};
}  // namespace BloomFilter